package log

import (
	"strconv"
	"strings"
)

//FmtField define abstract formatting field
type FmtField interface {
	//assemble field content as line with seperator
	AssembleAsLineSeperator(*strings.Builder, *HandlerCommon)
	//assemble field content as json string
	AssembleAsJSON(*strings.Builder, *HandlerCommon)
}

//FFArrInt64 define FmtField for []int64
type FFArrInt64 []int64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFArrInt64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	for i := 0; i < len(f); i++ {
		buff.WriteString(strconv.FormatInt(f[i], 10))
		if i < len(f)-1 {
			buff.WriteByte(',')
		}
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFArrInt64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('[')
	f.AssembleAsLineSeperator(buff, com)
	buff.WriteByte(']')
}

//FFArrUint64 define FmtField for []uint64
type FFArrUint64 []uint64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFArrUint64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	for i := 0; i < len(f); i++ {
		buff.WriteString(strconv.FormatUint(f[i], 10))
		if i < len(f)-1 {
			buff.WriteByte(',')
		}
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFArrUint64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('[')
	f.AssembleAsLineSeperator(buff, com)
	buff.WriteByte(']')
}

//FFArrFloat64 define FmtField for []float64
type FFArrFloat64 []float64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFArrFloat64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	for i := 0; i < len(f); i++ {
		buff.WriteString(strconv.FormatFloat(f[i], 'g', 6, 64))
		if i < len(f)-1 {
			buff.WriteByte(',')
		}
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFArrFloat64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('[')
	f.AssembleAsLineSeperator(buff, com)
	buff.WriteByte(']')
}

//FFArrString define FmtField for []string
type FFArrString []string

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFArrString) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	for i := 0; i < len(f); i++ {
		buff.WriteString(f[i])
		if i < len(f)-1 {
			buff.WriteByte(',')
		}
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFArrString) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('[')
	for i := 0; i < len(f); i++ {
		buff.WriteByte('"')
		buff.WriteString(f[i])
		buff.WriteByte('"')
		if i < len(f)-1 {
			buff.WriteByte(',')
		}
	}
	buff.WriteByte(']')
}

//FFMapStringInt64 define FmtField for map[string]int64
type FFMapStringInt64 map[string]int64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFMapStringInt64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteString(k)
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatInt(v, 10))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFMapStringInt64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('{')
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteByte('"')
		buff.WriteString(k)
		buff.WriteByte('"')
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatInt(v, 10))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
	buff.WriteByte('}')
}

//FFMapStringUint64 define FmtField for map[string]uint64
type FFMapStringUint64 map[string]uint64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFMapStringUint64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteString(k)
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatUint(v, 10))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFMapStringUint64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('{')
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteByte('"')
		buff.WriteString(k)
		buff.WriteByte('"')
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatUint(v, 10))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
	buff.WriteByte('}')
}

//FFMapStringFloat64 define FmtField for map[string]float64
type FFMapStringFloat64 map[string]float64

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFMapStringFloat64) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteString(k)
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatFloat(v, 'g', 6, 64))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFMapStringFloat64) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('{')
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteByte('"')
		buff.WriteString(k)
		buff.WriteByte('"')
		buff.WriteByte(':')
		buff.WriteString(strconv.FormatFloat(v, 'g', 6, 64))
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
	buff.WriteByte('}')
}

//FFMapStringString define FmtField for map[string]string
type FFMapStringString map[string]string

//AssembleAsLineSeperator implement FmtField.AssembleAsLineSeperator()
func (f FFMapStringString) AssembleAsLineSeperator(buff *strings.Builder, com *HandlerCommon) {
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteString(k)
		buff.WriteByte(':')
		buff.WriteString(v)
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
}

//AssembleAsJSON implement FmtField.AssembleAsJSON()
func (f FFMapStringString) AssembleAsJSON(buff *strings.Builder, com *HandlerCommon) {
	buff.WriteByte('{')
	n := len(f)
	i := 0
	for k, v := range f {
		buff.WriteByte('"')
		buff.WriteString(k)
		buff.WriteByte('"')
		buff.WriteByte(':')
		buff.WriteByte('"')
		buff.WriteString(v)
		buff.WriteByte('"')
		if i < n-1 {
			buff.WriteByte(',')
		}
		i++
	}
	buff.WriteByte('}')
}
